package com.example.loginregister.View

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.example.loginregister.Model.DotState
import com.example.loginregister.Model.DotModel
import com.example.loginregister.R
import com.example.loginregister.Tools.dpToPx
import java.lang.Integer.min
import java.lang.StringBuilder

class UnlockPatternView(context: Context, attrs: AttributeSet) : View(context, attrs) {

    private var mRadius = dpToPx(40)
    private val mSpace = dpToPx(25)
    private val mStateStrokeWidth = 10f

    private var start_cx = 0f
    private var start_cy = 0f

    private val mNormalPaint: Paint by lazy {
        Paint().apply {
            isAntiAlias = true
            style = Paint.Style.FILL
        }
    }
    private val mStatePaint: Paint by lazy {
        Paint().apply {
            isAntiAlias = true
            style = Paint.Style.STROKE
            strokeWidth = mStateStrokeWidth
        }
    }
    private val mSmallDotPaint: Paint by lazy {
        Paint().apply {
            isAntiAlias = true
            style = Paint.Style.FILL
        }
    }
    private val mLinePaint: Paint by lazy {
        Paint().apply {
            isAntiAlias = true
            style = Paint.Style.STROKE
            color = resources.getColor(R.color.white)
            strokeWidth = mStateStrokeWidth
        }
    }

    private var lastSelectedDot: DotModel? = null
    private val dotModels = arrayListOf<DotModel>()
    private val pwdDots = arrayListOf<DotModel>()
    private var mPath = Path()
    private var mMovePath = Path()
    private var mLines = arrayListOf<Path>()

    private val pwdBuilder = StringBuilder()

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        var mWidth = 0
        var mHeight = 0

        mWidth = when (MeasureSpec.getMode(widthMeasureSpec)) {
            MeasureSpec.EXACTLY -> MeasureSpec.getSize(widthMeasureSpec)
            else -> (6 * mRadius + 4 * mSpace).toInt()
        }

        mHeight = when (MeasureSpec.getMode(heightMeasureSpec)) {
            MeasureSpec.EXACTLY -> MeasureSpec.getSize(heightMeasureSpec)
            else -> (6 * mRadius + 4 * mSpace).toInt()
        }
        setMeasuredDimension(mWidth, mHeight)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        mRadius = (min(width, height) - 4 * mSpace) / 6

        start_cx = ((width - min(width, height)) / 2 + mRadius + mSpace)
        start_cy = ((height - min(width, height)) / 2 + mRadius + mSpace)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        drawLine(canvas)
        drawCircle(canvas)
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when (event?.action) {
            MotionEvent.ACTION_DOWN -> {
                touch(event.x, event.y)
            }

            MotionEvent.ACTION_MOVE -> {
                touch(event.x, event.y)
            }

            MotionEvent.ACTION_UP -> {
                touch(event.x,event.y)
                refresh()
            }
        }
        return true
    }



    private fun touch(x: Float, y: Float) {
        val dot = isInDot(x, y)
        if (dot != null) {
            if (!pwdDots.contains(dot)) {
                if (lastSelectedDot != null) {
                    mPath.moveTo(lastSelectedDot!!.cx, lastSelectedDot!!.cy)
                    mPath.lineTo(dot.cx, dot.cy)
                    mLines.add(mPath)
                }
                lastSelectedDot = dot
                pwdDots.add(dot.apply { state = DotState.Selected })
            }
        }
        if (lastSelectedDot!=null) {
            addMoveLine(x,y)
        }

        invalidate()
    }

    //密码生成器
    private fun pwdBuilder():String{
        pwdDots.forEach {
            pwdBuilder.append(it.num)
        }
        return pwdBuilder.toString()
    }

    //判断是否在点的内部
    private fun isInDot(x: Float, y: Float): DotModel? {
        dotModels.forEach {
            if (it.containDot(x, y)) {
                return it
            }
        }
        return null
    }

    //添加随手指移动的绘制路线
    private fun addMoveLine(x: Float,y: Float){
        mMovePath.reset()
        mMovePath.moveTo(lastSelectedDot!!.cx, lastSelectedDot!!.cy)
        mMovePath.lineTo(x, y)
    }

    //刷新
    private fun refresh() {
        mMovePath.reset()
        if(pwdBuilder()!="1598"){
            pwdDots.forEach { it.state = DotState.Error }
        }
        postDelayed({
            lastSelectedDot = null
            pwdBuilder.clear()
            pwdDots.forEach { it.state = DotState.Normal }
            pwdDots.clear()
            mLines.forEach { it.reset() }
            mLines.clear()
            invalidate()
        },500)
    }

    //根据不同状态绘制圆点
    @SuppressLint("ResourceAsColor")
    private fun drawCircle(canvas: Canvas) {
        //绘制初始背景
        var num = 1
        for (i in 0..2) {
            for (j in 0..2) {
                val cx = start_cx + j * (2 * mRadius + mSpace)
                val cy = start_cy + i * (2 * mRadius + mSpace)
                canvas.drawCircle(
                    cx,
                    cy,
                    mRadius,
                    mNormalPaint.apply { color = resources.getColor(R.color.normal_gray) })
                dotModels.add(DotModel(num++, cx, cy, mRadius))
            }
        }
        //重新绘制选中点
        pwdDots.forEach {
            it.apply {
                when (state) {
                    DotState.Selected -> {
                        canvas.drawCircle(
                            cx,
                            cy,
                            20f,
                            mSmallDotPaint.apply {
                                color = resources.getColor(R.color.small_dot_color)
                            })
                        canvas.drawCircle(
                            cx,
                            cy,
                            mRadius,
                            mStatePaint.apply { color = resources.getColor(R.color.selected_blue) })
                    }

                    DotState.Error -> {
                        canvas.drawCircle(
                            cx,
                            cy,
                            20f,
                            mSmallDotPaint.apply { color = resources.getColor(R.color.error_red) })
                        canvas.drawCircle(
                            cx,
                            cy,
                            mRadius,
                            mStatePaint.apply { color = resources.getColor(R.color.error_red) })
                    }

                    DotState.Normal -> {
                        canvas.drawCircle(cx, cy, mRadius, mNormalPaint)
                    }
                }
            }
        }
    }

    private fun drawLine(canvas: Canvas) {
        canvas.drawPath(mMovePath, mLinePaint)
        mLines.forEach { canvas.drawPath(it,mLinePaint) }
    }
}